#include "dev.h"

#include "mod_port.h"
#include "rtc.h"
#include "data.h"
#include "alarm.h"
#include "mod_gun.h"
#include "mod_emeter.h"
#include "mod_rfcard.h"
#include "mod_led.h"
#include "mod_eth.h"
#include "mod_gprs.h"
#include "platform.h"
#include "mod_gui.h"

#include <string.h>
#include <stdio.h>

struct module_info{
	  uint32_t id; 
    int32_t init_state;
	  int32_t vol;
	  int32_t currt;
    int8_t gun_link;
   	int32_t meter_kwh;
    int32_t poll_cnt;
    uint32_t time_cnt;
    int32_t need_vol;   //需求电压
    int32_t need_currt; //需求电流
    int32_t left_time;  //剩余时间，分钟
    int32_t soc; 
};

struct DevInfo{
    uint8_t gunnum;  //实际使用的枪数    
	  struct module_info module[DEV_CHARGE_GUN_CNT];
	  int32_t net_state;
    uint32_t cnt;
};

static struct DevInfo Dev = {0};
struct ClientUserGunInfo gun_status[DEV_CHARGE_GUN_CNT]={0};
static const struct ClientCallback *client_callback = NULL;

void dev_set_client_callback(const struct ClientCallback *callback){
    client_callback = callback;
}

int32_t dev_card_swip(uint8_t gun_id, char_t *card_id, char_t *pwd, uint32_t type, uint32_t value){
    if ((client_callback != NULL) && (client_callback->card_swip != NULL)){
        return client_callback->card_swip(gun_id, card_id, pwd, type, value);
    }
    return -1;
}

void sync_gun_state(int gun_id){    
    int32_t gun_link = dev_get_gun_link(gun_id);
    if (Dev.module[gun_id - 1].gun_link != gun_link){
        Dev.module[gun_id - 1].gun_link = gun_link;
        gun_status[gun_id-1].car_connection_stat = gun_link;
    }
		
		int32_t relay_state = dev_get_relay_state(gun_id);
		if (gun_status[gun_id-1].relay_state != relay_state){
			   gun_status[gun_id-1].relay_state = relay_state;
		}
}

struct ClientUserGunInfo *dev_get_user_client_gun_data(void){
    return &gun_status[0];
}

int32_t dev_rfcard_read(char_t *card_id){
    return rfcard_read(card_id);
}


//063000
static int32_t dev_get_time_sec(char_t *str){
    int32_t hour = 0;
    int32_t min = 0;
    int32_t sec = 0;
    sscanf(str, "%2d%2d%2d", &hour, &min, &sec);    
    return hour * 60 * 60 + min * 60 + sec;
}


void dev_adv_light_mgr(void){
    static char_t light_state = 0; //0 关闭状态 1 为打开状态
    int32_t currt_sec = rtc_get_currt_time_sec();
    char_t buf_light_on[20]={0};
    data_getstr("advon", buf_light_on, sizeof(buf_light_on));
    char_t buf_light_off[20]={0};
    data_getstr("advoff", buf_light_off, sizeof(buf_light_off));

    int32_t lighton_sec = dev_get_time_sec(buf_light_on);
    int32_t lightoff_sec = dev_get_time_sec(buf_light_off);
    if (lighton_sec < lightoff_sec){
        if ((currt_sec > lighton_sec) && (currt_sec <= lightoff_sec)){
            //light on
            if (light_state == 0){
                light_state = 1;
                port_light_close();
            }            
        }else{
            //light off
            if(light_state == 1){
                light_state = 0;
                port_light_open();
            }
        }
    }else{
        if((currt_sec > lighton_sec) || (currt_sec < lightoff_sec)){
            //light on
            if (light_state == 0){
                light_state = 1;
                port_light_close(); 
            }            
        }else{
            //light off
            if(light_state == 1){
                light_state = 0;
                port_light_open();
            }            
        }
    }    
}



int32_t dev_reboot(void){
    os_reboot();
    return 0;
}

static void deal_relay_alarm(struct module_info *m){
    uint8_t state = gun_get_relay_alarm(m->id);
    if (state == RELAY_ALARM_STUCK){
        alarm_deal(m->id, DC_ALARM_AC_CONTACT_ADHESION0X23, 0x01);
    }else if (state == RELAY_ALARM_UNCLOSE){
        alarm_deal(m->id, DC_ALARM_AC_CONTACOR0X23, 0x01);
    }
}

void update_emeter_kwh(struct module_info *m){
    m->meter_kwh = emeter_getvalue(m->id, EM_TYPE_KWH); 
    gun_status[m->id-1].meter_kwh_num = m->meter_kwh;
}

void updata_emeter_vol_current(struct module_info *m){
    m->vol = controler_get_vol(m->id);
    m->currt = controler_get_current(m->id);
    m->need_vol = controler_get_need_vol(m->id);
    m->need_currt = controler_get_need_currt(m->id);
    m->left_time = controler_get_left_time(m->id);
    m->soc = controler_get_soc(m->id);
}


static void dev_alarm_notify(int32_t gunid, const char_t *alarmcode, char_t state){
    if ((client_callback == NULL) 
        || (client_callback->error_occured == NULL) 
        || client_callback->error_recovered == NULL){
        
        return;
    }
    
    if (state == ALARM_OCCURED){
        client_callback->error_occured(gunid, alarmcode);
    }else{
        client_callback->error_recovered(gunid, alarmcode);
    }
}


void dev_net_connect_state(int32_t state){
    Dev.net_state = state;
}

int32_t dev_stop_charge_up_client(uint8_t gun_id, const char_t *reasion){
    if (client_callback != NULL && client_callback->charge_stoped != NULL){
        return client_callback->charge_stoped(gun_id, reasion);
    }
    return 0;
}

int32_t dev_state_charge_idle(uint8_t gun_id){
    if (client_callback != NULL && client_callback->charge_idle != NULL){
        return client_callback->charge_idle(gun_id);
    }
    return 0;
}

int32_t dev_state_change_up_client(uint8_t gun_id){
    if (client_callback != NULL && client_callback->state_reup != NULL){
        return client_callback->state_reup(gun_id);
    }
    return 0;
}

void dev_enable_swipcard(void){
    rfcard_set(RFCARD_ENABLE);
}

void dev_disable_swipcard(void){
    rfcard_set(RFCARD_DISABLE);
}

int32_t dev_sync_time(uint64_t sec){
    rtc_set_time_by_sec(sec);
    controler_set_time();
    return 0;
}
int32_t dev_sync_datetime(int year, uint8_t mon, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec,uint8_t week)
{
	  rtc_set_time(year,mon,day,hour,min,sec,week);
    controler_set_time();
    return 0;
}
int32_t dev_idle_init(uint8_t gun_id){
    dev_state_charge_idle(gun_id);
    return 0;
}

void dev_set_net_state(uint8_t state){
    Dev.net_state = state;
}

int32_t dev_get_net_state(void){
    return Dev.net_state;
}

int32_t dev_alarm_init(uint8_t gun_id){
    dev_state_change_up_client(gun_id);
    return 0;
}

int32_t dev_get_meter_kwh(uint8_t gun_id){
    return Dev.module[gun_id-1].meter_kwh;
}

int32_t dev_get_vol(uint8_t gun_id){
    return Dev.module[gun_id-1].vol;
}

int32_t dev_get_current(uint8_t gun_id){
    return Dev.module[gun_id-1].currt;
}

int32_t dev_get_need_vol(uint8_t gun_id) {
    return Dev.module[gun_id-1].need_vol;
}
int32_t dev_get_need_currt(uint8_t gun_id) {
    return Dev.module[gun_id-1].need_currt;
}
int32_t dev_get_left_time(uint8_t gun_id) {
    return Dev.module[gun_id-1].left_time;
}
int32_t dev_get_soc(uint8_t gun_id){
    return Dev.module[gun_id-1].soc;
}

int32_t dev_is_use_net(void){
    if (data_getint("chargetest") == 0)  {
        return 1;
    }
    return 0;
}

//10ms 调用一次
void module_poll(struct module_info *m){
    update_emeter_kwh(m);
    updata_emeter_vol_current(m); //ac dc 不同
    sync_gun_state(m->id);  
    alarm_deal(m->id, DC_ALARM_BUTTON, port_is_close(PORT_STATE_ESTOP)?0x01:0x0);
    deal_relay_alarm(m);

    m->time_cnt++;
    alarm_deal(m->id, DC_ALARM_ELEC_METER, emeter_isalarm(m->id)?0x01:0x0);
    
    if (m->time_cnt %10 == 0){
        controler_keeplive(m->id);
    }    
}

int32_t module_init(struct module_info *m, int32_t id){
	m->id = id;
    m->init_state = 0;
	m->gun_link = GUN_UNCONNECT_CAR;
	m->meter_kwh = 0;
	m->poll_cnt = 0;
    m->time_cnt = 0;

	return 0;
}

void dev_poll(void){

    Dev.cnt++;
    
    for (int32_t i=0;i<Dev.gunnum;i++){
        module_poll(&Dev.module[i]);
    }
    
    //更新网络
    
    //广告灯控制
    if (Dev.cnt % (10 * 5) == 0){
        dev_adv_light_mgr();
    }

}

int32_t dev_init(void){
	Dev.net_state = 0;
    Dev.gunnum = data_getint("gunnum");
	if (led_init() != 0){
		return -1;
	}   

    if (gun_init() != 0){
        return -1;
    }

	if (rfcard_init() != 0){
		return -1;
	}
    
    struct EmeterInitPara emeter_para = {0};
    emeter_para.num = Dev.gunnum;
    emeter_para.mode = data_getint("emmode");
    emeter_para.baud = data_getint("embaud");
    data_getstr("emidl", emeter_para.left_id, sizeof(emeter_para.left_id));
    data_getstr("emidr", emeter_para.right_id, sizeof(emeter_para.right_id));
    if (emeter_init(&emeter_para) != 0){
        return -1;
    }
    
    if (alarm_init(dev_alarm_notify) != 0){
        return -1;
    }

	for(int32_t i=0;i<Dev.gunnum;i++){
		if (module_init(&Dev.module[i], i+1) != 0){
			return -1;
		}
	}
    if (gui_init() != 0){
        return -1;
    }
    if (controler_init() != 0){
        return -1;
    }
    data_set_sys_power_on_cnt();
    T_TimeFmt tim={0};
    rtc_get_current_time(&tim);
    data_set_last_power_on_time(&tim);
    

    char_t addr[20]={0};
    data_getstr("rip", addr, sizeof(addr));
    uint32_t port = data_getint("rport");
    if (net_init(addr, port) != 0){
        return -1;
    }   
	  return 0;
}


